﻿/*
 * 
 * Responsabilidade:
 * Controlar o estado da sessão de usuário
 * Controlar a aparência de paneis dentro da janela do formulãrio principal
 * Instanciar os demais objetos principas do central do controle
 * 
 * Instanciado pelo frmPrincipal...Load()
 * 
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;
using System.Windows.Forms;

namespace J_Controle
{
    public enum EstadoSessao
    {
        Indefinido,
        Inicial,
        DlgByte,
        DlgChar,
        DlgTeste,
        DlgDash,
        DbgTest1,
        Ajuda
    }

    public class ControladorSessao
    {
        FrmPrincipal FormAtual;
        ConfigHW CnfHwAtual;

        EstadoSessao EstadoAtual = EstadoSessao.Indefinido;
        ControladorDialogo CtlOpAtual;
        SerialPort Porta;

        public DialogoByte DlgByte;
        public DialogoChar DlgChar;
        public DialogoTeste DlgTeste;
        public DialogoDashboard DlgDash;
        


        // ========================================
        //
        // Constructor
        public ControladorSessao(FrmPrincipal prmForm)
        {
            ConfigPorta cp;

            FormAtual = prmForm;

            // criar objetos principais
            Porta = new SerialPort();
            DlgByte = new DialogoByte(FormAtual.pnlDiaByte);
            DlgChar = new DialogoChar(FormAtual.pnlDiaChar);
            DlgTeste = new DialogoTeste(FormAtual.pnlTest);

            // parametrizaçaõ inicial
            Configuracao.IniRegistry();
            Configuracao.LerRegistry(out cp, out CnfHwAtual);
            SetarCnfPorta(cp);
            //SetarCnfPorta(new ConfigPorta());

            // Entrar estado / mostrar paineil inicial
            EntrarEstado(EstadoSessao.Inicial);
        }

        // ===========================================
        //
        // Métodos gerais de gerenciamento de estado da sessão

        public void EntrarEstado(EstadoSessao novo)
        {
            // testar se precisa ação
            if (novo == EstadoAtual) return;

            // testar se precisar terminar uma coisa
            switch (EstadoAtual)
            {
                case EstadoSessao.DlgByte:
                case EstadoSessao.DlgChar:
                case EstadoSessao.DlgTeste:
                    if(!CtlOpAtual.Desconectar()) return;
                    break;
                default: break;
            }

            // iniciar aparência do novo estado, conectar controladores
            switch (novo)
            {
                case EstadoSessao.Inicial:
                    FormAtual.pnlInicial.Dock = System.Windows.Forms.DockStyle.Fill;
                    FormAtual.pictureBox1.Dock = System.Windows.Forms.DockStyle.Fill;
                    FormAtual.pnlInicial.Show();
                    FormAtual.pnlInicial.BringToFront();
                    FormAtual.pnlInicial.Refresh();
                    break;

                case EstadoSessao.DlgByte:
                    CtlOpAtual = DlgByte;
                    DlgByte.Visualizar();
                    DlgByte.Conectar(Porta, CnfHwAtual);
                    break;

                case EstadoSessao.DlgChar:
                    CtlOpAtual = DlgChar;
                    DlgChar.Visualizar();
                    if (!DlgChar.Conectar(Porta, CnfHwAtual)) DlgChar.Desconectar();
                    break;

                case EstadoSessao.DlgTeste:
                    CtlOpAtual = DlgTeste;
                    DlgTeste.Visualizar();
                    if (!DlgTeste.Conectar(Porta, CnfHwAtual)) DlgChar.Desconectar();
                    break;

                default:
                    throw new NotImplementedException("Não consigo entrar o estado " + novo.ToString());
            }

            
            // transição do estado
            EstadoAtual = novo;
        }
        public void OnApplicationExit(object sender, EventArgs e)
        {
            // When the application is exiting, save configuratioon data

            try
            {
                // Ignore any errors that might occur
                //MessageBox.Show("OnApplicationExit");
                Configuracao.GravarRegistry(LerCnfPorta(), CnfHwAtual);
            }
            catch { }
        }


        // =======================================
        //
        // Métodos principais do menu

        // ----------- Menu Porta ---------------
        public void MnuPorCon()
        {
            // fiscalizar se manipulação da porta é ligítimo no estado atual
            switch(EstadoAtual)
            {
                case EstadoSessao.Inicial:
                case EstadoSessao.DlgByte:
                    // legítimo
                    break;
                default:
                    MessageBox.Show("Não pode configurar a porta serial durante uma operação " + EstadoAtual.ToString());
                    return;
            }

            // fiscalizar se a porte é devidamente fechada
            if (Porta.IsOpen)
            {
                MessageBox.Show("Não pode configurar com porta aberta.");
                return;
            }

            ConfigPorta cp = LerCnfPorta();
            FrmConfigPorta fp = new FrmConfigPorta(cp);
            fp.ShowDialog();
            SetarCnfPorta(cp);
        }
        public void MnuPorAbr()
        {
            // fiscalizar se manipulação da porta é ligítimo no estado atual
            switch (EstadoAtual)
            {
                case EstadoSessao.Inicial:
                case EstadoSessao.DlgByte:
                    // legítimo
                    break;
                default:
                    MessageBox.Show("Não pode abrir a porta serial durante uma operação " + EstadoAtual.ToString());
                    return;
            }
            Porta.Open();
            FormAtual.StatusAberto.Text = (Porta.IsOpen) ? "Aberto" : "Fechado";
            FormAtual.Refresh();

        }
        public void MnuPorFec()
        {
            // fiscalizar se manipulação da porta é ligítimo no estado atual
            switch (EstadoAtual)
            {
                case EstadoSessao.Inicial:
                case EstadoSessao.DlgByte:
                    // legítimo
                    break;
                default:
                    MessageBox.Show("Não pode fechar a porta serial durante uma operação " + EstadoAtual.ToString());
                    return;
            }
            Porta.Close();
            FormAtual.StatusAberto.Text = (Porta.IsOpen) ? "Aberto" : "Fechado";
            FormAtual.Refresh();
        }

        // ----------- Menu Debug ---------------
        public void MnuDbgTs1()
        {
            FormAtual.pnlDebugTest1.Dock = System.Windows.Forms.DockStyle.Fill;
            FormAtual.pnlDebugTest1.Show();
            FormAtual.pnlDebugTest1.BringToFront();
            FormAtual.pnlDebugTest1.Refresh();
        }

        // ===========================================
        //
        // Métodos de gerenciamento da porta serial

        void SetarCnfPorta(ConfigPorta prmConfig)
        {
            // fiscalizar porta = fechada. Senão, erro do SW
            if (Porta.IsOpen) throw new InvalidOperationException("Não pode configurar porta aberta. Erro de SW!");

            // definir os parâmetros da porta serial
            Porta.PortName = prmConfig.Nome; 
            Porta.BaudRate = prmConfig.BpsVal;
            Porta.StopBits = prmConfig.StopVal;
            Porta.Parity = prmConfig.PtyVal;
            Porta.ParityReplace = prmConfig.ParityReplaceVal;
            Porta.ReceivedBytesThreshold = ConfigPorta.ReceivedBytesThreshold;

            // Visualizar os principais no formulário
            FormAtual.StatusNome.Text = prmConfig.Nome;
            FormAtual.StatusBps.Text = prmConfig.BpsText;
            FormAtual.StatusAberto.Text = (Porta.IsOpen) ? "Aberto" : "Fechado";
        }
        ConfigPorta LerCnfPorta()
        {
            // fiscalizar porta = fechada. Senão, erro do SW
            if (Porta.IsOpen) throw new InvalidOperationException("Não pode configurar porta aberta. Erro de SW!");

            // ler os parâmetros da porta serial
            ConfigPorta cc = new ConfigPorta();
            cc.Nome = Porta.PortName;
            cc.BpsVal = Porta.BaudRate;
            cc.StopVal = Porta.StopBits;
            cc.PtyVal = Porta.Parity;
            cc.ParityReplaceVal = Porta.ParityReplace;
            return cc;
        }

    }
}
